package com.ssy.lingxi.purchase.serviceimpl.tender;

import cn.hutool.core.bean.BeanUtil;
import com.ssy.lingxi.common.exception.BusinessException;
import com.ssy.lingxi.common.model.dto.UserLoginCacheDTO;
import com.ssy.lingxi.common.model.vo.PageVO;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.message.api.constant.MessageTemplateCode;
import com.ssy.lingxi.message.api.feign.SystemMessageControllerFeign;
import com.ssy.lingxi.message.api.vo.request.SystemMessageRequest;
import com.ssy.lingxi.purchase.api.dto.request.tender.*;
import com.ssy.lingxi.purchase.api.enums.tender.*;
import com.ssy.lingxi.purchase.entity.tender.*;
import com.ssy.lingxi.purchase.repository.tender.ExpertExtractRecordRepository;
import com.ssy.lingxi.purchase.repository.tender.InviteTenderInCheckRecordRepository;
import com.ssy.lingxi.purchase.repository.tender.InviteTenderRepository;
import com.ssy.lingxi.purchase.repository.tender.SubmitTenderOutCheckRecordRepository;
import com.ssy.lingxi.purchase.service.tender.IExpertExtractRecordService;
import org.apache.commons.lang.StringUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 评标专家库实现类
 * @author jw.chen
 * @version 2.0.0
 * @date 2020/6/22
 */
@Service
public class ExpertExtractRecordServiceImpl implements IExpertExtractRecordService {

    @Resource
    private ExpertExtractRecordRepository expertExtractRecordRepository;

    @Resource
    private InviteTenderInCheckRecordRepository inviteTenderInCheckRecordRepository;

    @Resource
    private InviteTenderRepository inviteTenderRepository;

    @Resource
    private SubmitTenderOutCheckRecordRepository submitTenderOutCheckRecordRepository;

    @Resource
    private SystemMessageControllerFeign systemMessageControllerFeign;

    /**
     * 查询专家评标列表
     * @param pageVO 分页实体
     * @param expertExtractRecordQueryRequest 评标专家库
     * @return
     */
    @Override
    public Page<ExpertExtractRecord> getExpertExtractRecordList(UserLoginCacheDTO sysUser, PageVO pageVO, ExpertExtractRecordQueryRequest expertExtractRecordQueryRequest){
        Pageable page = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize());
        return expertExtractRecordRepository.findAll(getSpecification(sysUser, expertExtractRecordQueryRequest), page);
    }

    /**
     * 查询专家评标
     * @return id
     */
    @Override
    public ExpertExtractRecord getExpertExtractRecord(UserLoginCacheDTO sysUser, Long id){
        return expertExtractRecordRepository.findById(id).orElse(null);
    }

    /**
     * 修改专家评标状态
     * @param sysUser
     * @param expertExtractStatusRequest
     * @return
     */
    @Override
    public Boolean updateExpertExtractStatus(UserLoginCacheDTO sysUser, ExpertExtractStatusRequest expertExtractStatusRequest) {
        Long id = expertExtractStatusRequest.getId();
        Boolean status = expertExtractStatusRequest.getStatus();
        String remark = expertExtractStatusRequest.getRemark();
        if(id != null){
            ExpertExtractRecord expertExtractRecord = expertExtractRecordRepository.findById(id).orElse(null);
            if(expertExtractRecord != null){
                InviteTender inviteTender = expertExtractRecord.getExpertExtract().getInviteTender();
                //招标内部状态
                InviteTenderInCheckRecord inviteTenderInCheckRecord = new InviteTenderInCheckRecord();
                Integer expertExtractStatus;

                List<SystemMessageRequest> systemMessageRequestList = new ArrayList<>();
                if(status){
                    expertExtractStatus = ExpertExtractStatusEnum.Confirm.getCode();
                    inviteTenderInCheckRecord.setOperationValue(TenderStatusEnum.RECEIVE_EVALUATION_NOTICE.getMessage());

                    //发送消息
                    SystemMessageRequest systemMessageRequest = new SystemMessageRequest();
                    systemMessageRequest.setMemberId(inviteTender.getMemberId());
                    systemMessageRequest.setRoleId(inviteTender.getMemberRoleId());
                    systemMessageRequest.setMessageNotice(MessageTemplateCode.bidding_expert_extract_agree);
                    systemMessageRequestList.add(systemMessageRequest);
                }else{
                    expertExtractStatus = ExpertExtractStatusEnum.Refuse.getCode();
                    inviteTenderInCheckRecord.setOperationValue(TenderStatusEnum.REFUSE_EVALUATION_NOTICE.getMessage());

                    //发送消息
                    SystemMessageRequest systemMessageRequest = new SystemMessageRequest();
                    systemMessageRequest.setMemberId(inviteTender.getMemberId());
                    systemMessageRequest.setRoleId(inviteTender.getMemberRoleId());
                    systemMessageRequest.setMessageNotice(MessageTemplateCode.bidding_expert_extract_refuse);
                    systemMessageRequestList.add(systemMessageRequest);
                }
                expertExtractRecord.setStatus(expertExtractStatus);
                expertExtractRecord.setRemark(remark);
                expertExtractRecordRepository.saveAndFlush(expertExtractRecord);

                try {
                    //发送消息
                    systemMessageControllerFeign.batchSendSystemMessage(systemMessageRequestList);
                }catch (Exception e){
                    e.printStackTrace();
                }

                inviteTenderInCheckRecord.setStatusValue(ExpertExtractStatusEnum.getMessage(expertExtractStatus) + TenderStatusEnum.EVALUATION_NOTICE.getMessage());
                inviteTenderInCheckRecord.setUserId(sysUser.getUserId());
                inviteTenderInCheckRecord.setUserName(sysUser.getUserName());
                inviteTenderInCheckRecord.setUserJobTitle(sysUser.getUserJobTitle());
                inviteTenderInCheckRecord.setUserOrgName(sysUser.getUserOrgName());
                inviteTenderInCheckRecord.setMemberId(sysUser.getMemberId());
                inviteTenderInCheckRecord.setMemberName(sysUser.getCompany());
                inviteTenderInCheckRecord.setMemberRoleId(sysUser.getMemberRoleId());
                inviteTenderInCheckRecord.setMemberRoleName(sysUser.getMemberRoleName());
                inviteTenderInCheckRecord.setCheckRemark(remark);
                inviteTenderInCheckRecord.setCreateTime(System.currentTimeMillis());
                inviteTenderInCheckRecord.setInviteTenderId(expertExtractRecord.getExpertExtract().getInviteTender().getId());
                inviteTenderInCheckRecordRepository.saveAndFlush(inviteTenderInCheckRecord);

                return true;
            }
        }
        throw new BusinessException(ResponseCode.PURCHASE_TENDER_EXPERT_NOT_EXIST);
    }

    /**
     * 专家评标
     * @param sysUser
     * @param expertEvaluationTenderRequest
     * @return
     */
    @Transactional
    @Override
    public String evaluationTender(UserLoginCacheDTO sysUser, ExpertEvaluationTenderRequest expertEvaluationTenderRequest) {
        Long expertExtractRecordId = expertEvaluationTenderRequest.getId();
        ExpertExtractRecord expertExtractRecord = expertExtractRecordRepository.findById(expertExtractRecordId).orElse(null);
        if(expertExtractRecord == null){
            throw new BusinessException(ResponseCode.PURCHASE_EXPERT_EXTRACT_NOT_EXIST);
        }
        ExpertExtract expertExtract = expertExtractRecord.getExpertExtract();
        InviteTender inviteTender = expertExtract.getInviteTender();
        if(inviteTender != null){
            long evaluationStartTime = inviteTender.getEvaluationStartTime();
            long evaluationEndTime = inviteTender.getEvaluationEndTime();
            long now = System.currentTimeMillis();
            if(evaluationStartTime > now || evaluationEndTime < now){
                throw new BusinessException(ResponseCode.PURCHASE_INVITE_TENDER_Evaluation_TIME);
            }

            //评标内容
            List<SubmitTenderOutCheckRecord> submitTenderOutCheckRecordList = new ArrayList<>();
            List<EvaluationTenderRequest> evaluationTenderRequestList = expertEvaluationTenderRequest.getEvaluationTenderList();
            List<InviteTenderMember> memberList = inviteTender.getMemberList();
            List<EvaluationTenderOnline> evaluationTenderList = evaluationTenderRequestList.stream().map(evaluationTenderRequest -> {
                Long memberId = evaluationTenderRequest.getInviteTenderMemberId();
                InviteTenderMember inviteTenderMember = memberList.stream().filter(member -> member.getMemberId().longValue() == memberId.longValue()).findFirst().orElse(null);
                if (inviteTenderMember != null) {
                    inviteTenderMember.setSubmitTenderOutStatus(SubmitTenderOutStatusEnum.Not_Finish_Notice.getCode());
                    EvaluationTenderOnline evaluationTender = BeanUtil.copyProperties(evaluationTenderRequest, EvaluationTenderOnline.class);
                    evaluationTender.setInviteTenderMemberId(inviteTenderMember.getMemberId());
                    evaluationTender.setExpertExtractRecord(expertExtractRecord);

                    //记录投标外部状态
                    SubmitTenderOutCheckRecord submitTenderOutCheckRecord = new SubmitTenderOutCheckRecord();
                    submitTenderOutCheckRecord.setMemberRoleId(sysUser.getMemberRoleId());
                    submitTenderOutCheckRecord.setMemberRoleName(sysUser.getMemberRoleName());
                    submitTenderOutCheckRecord.setCreateTime(System.currentTimeMillis());
                    submitTenderOutCheckRecord.setSubmitTenderId(inviteTenderMember.getId());
                    submitTenderOutCheckRecord.setOperationValue(InviteTenderInOperationEnum.getMessage(InviteTenderInOperationEnum.Finish_Selection_Tender.getCode()));
                    submitTenderOutCheckRecord.setStatusValue(TenderStatusEnum.HAS_EVALUATION_NOTICE.getMessage());
                    submitTenderOutCheckRecordList.add(submitTenderOutCheckRecord);

                    return evaluationTender;
                }else{
                    return null;
                }
            }).filter(Objects::nonNull).collect(Collectors.toList());
            expertExtractRecord.setEvaluationTenderList(evaluationTenderList);
            expertExtractRecord.setStatus(ExpertExtractStatusEnum.Evaluation.getCode());
            expertExtractRecordRepository.saveAndFlush(expertExtractRecord);

            //推荐会员
            List<EvaluationTenderRecommendRequest> evaluationTenderRecommendList = expertEvaluationTenderRequest.getEvaluationTenderRecommendList();
            List<EvaluationTenderRecommend> recommendList = evaluationTenderRecommendList.stream().map(evaluationTenderRecommendRequest -> {
                EvaluationTenderRecommend evaluationTenderRecommend = BeanUtil.copyProperties(evaluationTenderRecommendRequest, EvaluationTenderRecommend.class);
                evaluationTenderRecommend.setUserName(sysUser.getUserName());
                evaluationTenderRecommend.setInviteTender(inviteTender);
                return evaluationTenderRecommend;
            }).collect(Collectors.toList());
            inviteTender.setEvaluationTenderRecommendList(recommendList);

            inviteTenderRepository.saveAndFlush(inviteTender);

            //招标内部状态
            InviteTenderInCheckRecord inviteTenderInCheckRecord = new InviteTenderInCheckRecord();
            inviteTenderInCheckRecord.setStatusValue(InviteTenderInStatusEnum.getMessage(InviteTenderInStatusEnum.Submitted_Selection_Tender.getCode()));
            inviteTenderInCheckRecord.setOperationValue(InviteTenderInOperationEnum.getMessage(InviteTenderInOperationEnum.Finish_Selection_Tender.getCode()));
            inviteTenderInCheckRecord.setUserId(sysUser.getUserId());
            inviteTenderInCheckRecord.setUserName(sysUser.getUserName());
            inviteTenderInCheckRecord.setUserJobTitle(sysUser.getUserJobTitle());
            inviteTenderInCheckRecord.setUserOrgName(sysUser.getUserOrgName());
            inviteTenderInCheckRecord.setMemberId(sysUser.getMemberId());
            inviteTenderInCheckRecord.setMemberName(sysUser.getCompany());
            inviteTenderInCheckRecord.setMemberRoleId(sysUser.getMemberRoleId());
            inviteTenderInCheckRecord.setMemberRoleName(sysUser.getMemberRoleName());
            inviteTenderInCheckRecord.setCreateTime(System.currentTimeMillis());
            inviteTenderInCheckRecord.setInviteTenderId(inviteTender.getId());
            inviteTenderInCheckRecordRepository.saveAndFlush(inviteTenderInCheckRecord);

            //投标会员内部状态
            submitTenderOutCheckRecordRepository.saveAll(submitTenderOutCheckRecordList);
            return ResponseCode.SUCCESS.getMessage();
        }else{
            throw new BusinessException(ResponseCode.PURCHASE_INVITE_TENDER_NOT_EXIST);
        }
    }

    /**
     * 构建查询条件
     * @param sysUser
     * @return
     */
    private Specification<ExpertExtractRecord> getSpecification(UserLoginCacheDTO sysUser, ExpertExtractRecordQueryRequest expertExtractRecordQueryRequest){
        return new Specification<ExpertExtractRecord>() {
            @Override
            public Predicate toPredicate(Root<ExpertExtractRecord> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                Predicate finalConditions = criteriaBuilder.conjunction();

                Long userId = sysUser.getUserId();
                Integer status = expertExtractRecordQueryRequest.getStatus();
                String inviteTenderCode = expertExtractRecordQueryRequest.getInviteTenderCode();
                String inviteTenderProjectName = expertExtractRecordQueryRequest.getInviteTenderProjectName();
                Long evaluationStartTime = expertExtractRecordQueryRequest.getEvaluationStartTime();
                Long evaluationEndTime = expertExtractRecordQueryRequest.getEvaluationEndTime();
                Boolean isOnlineEvaluation = expertExtractRecordQueryRequest.getIsOnlineEvaluation();

                //专家评标列表只显示待评标和待提交评标报告两种状态
                List<Integer> inviteTenderInStatusList = new ArrayList<>();
                inviteTenderInStatusList.add(InviteTenderInStatusEnum.Not_Selection_Tender.getCode());
                inviteTenderInStatusList.add(InviteTenderInStatusEnum.Submitted_Selection_Tender.getCode());
                finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.in(root.get("expertExtract").get("inviteTender").get("inviteTenderInStatus")).value(inviteTenderInStatusList));

                if(!StringUtils.isEmpty(inviteTenderCode)){
                    finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.like(root.get("expertExtract").get("inviteTender").get("code").as(String.class), "%" + inviteTenderCode + "%"));
                }

                if(!StringUtils.isEmpty(inviteTenderProjectName)){
                    finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.like(root.get("expertExtract").get("inviteTender").get("projectName").as(String.class), "%" + inviteTenderProjectName + "%"));
                }

                if(isOnlineEvaluation != null && isOnlineEvaluation){
                    finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.equal(root.get("expertExtract").get("inviteTender").get("isOnlineEvaluation"), true));
                }

                if(status != null && status > 0){
                    finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.equal(root.get("status"), status));
                }

                if(userId != null && userId> 0){
                    finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.equal(root.get("expert").get("expertUserId").as(Long.class), userId));
                }

                //评标时间
                if(evaluationStartTime != null && evaluationStartTime > 0 && evaluationEndTime != null && evaluationEndTime > 0){
                    finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.and(criteriaBuilder.ge(root.get("expertExtract").get("inviteTender").get("inviteTenderEndTime"), evaluationStartTime),criteriaBuilder.le(root.get("expertExtract").get("inviteTender").get("inviteTenderStartTime"), evaluationEndTime)));
                }else{
                    if(evaluationStartTime != null && evaluationStartTime > 0){
                        finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.ge(root.get("expertExtract").get("inviteTender").get("inviteTenderEndTime"), evaluationStartTime));
                    }
                    if(evaluationEndTime != null && evaluationEndTime > 0){
                        finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.le(root.get("expertExtract").get("inviteTender").get("inviteTenderStartTime"), evaluationEndTime));
                    }
                }

                //默认查询已发送状态以上并且是已评标以下的
                finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.gt(root.get("status"), ExpertExtractStatusEnum.Not_Send.getCode()));
                finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.lt(root.get("status"), ExpertExtractStatusEnum.Evaluation.getCode()));

                query.orderBy(criteriaBuilder.desc(root.get("id")));
                return finalConditions;
            }
        };
    }
}

